﻿using Microsoft.VisualStudio.SharePoint;
using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EnvDTE;

namespace SPVSX.DeploymentExtensions
{
    // Export attribute: Enables Visual Studio to discover and load this extension.
    [Export(typeof(ISharePointProjectExtension))]

    /// <summary>
    /// TODO: COMMENT
    /// 
    /// This code is a WIP and is in need of improved commenting, exception handling, and potentially
    /// factoring.  Please be nice.
    /// 
    /// Though this code is Open Source, in good faith it is requested that you consult the original author(s)
    /// before changing or re-using it for any public endeavour intended to provide similar functionality, or
    /// to fix simple bugs.  In other words, if you want to create SPVSX2, please let us know first.
    /// </summary>
    /// <remarks>@author Matt Smith, http://blog.mattsmith.co.nz</remarks>
    public class DeploymentProjectExtension : ISharePointProjectExtension
    {
        // Implements ISharePointProjectService.Initialize, which determines the behavior of the new property.
        public void Initialize(ISharePointProjectService projectService)
        {
            // Handle events for when a project property is changed.
            projectService.ProjectPropertiesRequested += new EventHandler<SharePointProjectPropertiesRequestedEventArgs>(projectService_ProjectPropertiesRequested);
        }

        void projectService_ProjectPropertiesRequested(object sender, SharePointProjectPropertiesRequestedEventArgs e)
        {
            if (!e.Project.IsSandboxedSolution)
            {
                // Add new properties to the SharePoint project.
                e.PropertySources.Add((object)new AutoCopyToSharePointRootProperty(e.Project));
                e.PropertySources.Add((object)new AutoCopyAssembliesProperty(e.Project));
                e.PropertySources.Add((object)new BuildOnCopyAssembliesProperty(e.Project));
            }
        }
    }

    public class AutoCopyToSharePointRootProperty: DeploymentPropertyBase
    {
        // Values for the project property.
        private const string customPropertyId = "SPVSX.DeploymentExtensions.AutoCopyToSharePointRootProperty";
        private const bool customPropertyDefaultValue = false;
        private const string propertyDescription = "Specifies whether or not SPVSX should automatically \"Copy to SharePoint Root\" whenever a deployable file is saved, for example an ASCX or ASPX file.";
        private const string propertyName = "Auto Copy to SharePoint Root";

        // Constructor.
        public AutoCopyToSharePointRootProperty(ISharePointProject project)
            : base(project)
        {
        }

        [DisplayName(propertyName)]
        [DescriptionAttribute(propertyDescription)]
        [DefaultValue(customPropertyDefaultValue)]
        [CategoryAttribute(propertyCategory)]
        public bool AutoCopyToSharePointRoot
        {
            get
            {
                return this.GetBoolValue(customPropertyId, customPropertyDefaultValue);
            }

            set
            {
                this.SetBoolValue(customPropertyId, value);
            }
        }

        public static bool GetFromProject(ISharePointProject p)
        {
            return new AutoCopyToSharePointRootProperty(p).AutoCopyToSharePointRoot;
        }
    }

    [DesignerCategory(propertyCategory)]
    public class AutoCopyAssembliesProperty : DeploymentPropertyBase
    {
        // Values for the project property.
        private const string customPropertyId = "SPVSX.DeploymentExtensions.AutoCopyAssembliesProperty";
        private const bool customPropertyDefaultValue = false;
        private const string propertyDescription = "Specifies whether or not SPVSX should automatically \"Copy to GAC/BIN\" whenever a SharePoint project is built.";
        private const string propertyName = "Auto Copy to GAC/BIN";

        // Constructor.
        public AutoCopyAssembliesProperty(ISharePointProject project)
            : base(project)
        {
        }

        [DisplayName(propertyName)]
        [DescriptionAttribute(propertyDescription)]
        [DefaultValue(customPropertyDefaultValue)]
        [CategoryAttribute(propertyCategory)]
        public bool AutoCopyAssemblies
        {
            get
            {
                return this.GetBoolValue(customPropertyId, customPropertyDefaultValue);
            }

            set
            {
                this.SetBoolValue(customPropertyId, value);
            }
        }

        public static bool GetFromProject(ISharePointProject p)
        {
            return new AutoCopyAssembliesProperty(p).AutoCopyAssemblies;
        }
    }

    [DesignerCategory(propertyCategory)]
    public class BuildOnCopyAssembliesProperty : DeploymentPropertyBase
    {
        // Values for the project property.
        private const string customPropertyId = "SPVSX.DeploymentExtensions.BuildOnCopyAssembliesProperty";
        private const bool customPropertyDefaultValue = false;
        private const string propertyDescription = "Specifies whether or not SPVSX should build the project before copying assemblies with \"Copy to GAC/BIN\".";
        private const string propertyName = "Build on Copy to GAC/BIN";

        // Constructor.
        public BuildOnCopyAssembliesProperty(ISharePointProject project)
            : base(project)
        {
        }

        [DisplayName(propertyName)]
        [DescriptionAttribute(propertyDescription)]
        [DefaultValue(customPropertyDefaultValue)]
        [CategoryAttribute(propertyCategory)]
        public bool BuildOnCopyAssemblies
        {
            get
            {
                return this.GetBoolValue(customPropertyId, customPropertyDefaultValue);
            }

            set
            {
                this.SetBoolValue(customPropertyId, value);
            }
        }

        public static bool GetFromProject(ISharePointProject p)
        {
            return new BuildOnCopyAssembliesProperty(p).BuildOnCopyAssemblies;
        }

    }

    // Internal helper class.
    public abstract class DeploymentPropertyBase
    {
        protected const string propertyCategory = "Quick Deploy (SPVSX)";

        protected ISharePointProject sharePointProject = null;

        protected DeploymentPropertyBase(ISharePointProject myProject)
        {
            sharePointProject = myProject;
        }

        internal string GetStringValue(string id, string defaultValue)
        {
            string propvalue = null;

            // Try to get the value from the .user file. The value of the property is 
            // stored in the variable "propvalue".
            if (!sharePointProject.ProjectUserFileData.TryGetValue(id, out propvalue))
            {
                // If we cannot get the value, then return the default value.
                propvalue = defaultValue;
            }

            return propvalue;
        }

        internal bool GetBoolValue(string id, bool defaultValue)
        {
            return bool.Parse(GetStringValue(id, defaultValue.ToString()));
        }

        internal void SetStringValue(string id, string value)
        {
            // If a key is not already in the .user file, add one.
            if (!sharePointProject.ProjectUserFileData.ContainsKey(id))
            {
                // Add a new key/value pair to the .user file.
                sharePointProject.ProjectUserFileData.Add(id, value.ToString());
            }
            else
            {
                // Set the property value.
                sharePointProject.ProjectUserFileData[id] = value.ToString();
            }
        }

        internal void SetBoolValue(string id, bool value)
        {
            SetStringValue(id, value.ToString());
        }
    }
}



